package com.example.zhu29.bledemo.activity;

import android.Manifest;
import android.annotation.SuppressLint;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import com.example.zhu29.bledemo.Contast;
import com.example.zhu29.bledemo.R;
import com.example.zhu29.bledemo.interFace.IBleConnectStatusListener;
import com.example.zhu29.bledemo.interFace.IBleIndicateListener;
import com.example.zhu29.bledemo.interFace.IBleScanListener;
import com.example.zhu29.bledemo.interFace.IBleStateListener;
import com.example.zhu29.bledemo.interFace.IBleWriteListener;
import com.example.zhu29.bledemo.interFace.IPermissionsListener;
import com.example.zhu29.bledemo.util.StringUtil;
import com.example.zhu29.bledemo.util.ZBleManager;
import com.example.zhu29.bledemo.util.ZDigitalTransTool;
import com.example.zhu29.bledemo.util.ZHexUtil;
import com.example.zhu29.bledemo.util.ZPermissionUtil;
import com.example.zhu29.bledemo.util.ZTimeTool;
import com.inuker.bluetooth.library.model.BleGattProfile;
import com.inuker.bluetooth.library.model.BleGattService;
import com.inuker.bluetooth.library.search.SearchResult;
import com.trello.rxlifecycle2.components.RxActivity;

import java.util.Arrays;
import java.util.concurrent.TimeUnit;

import io.reactivex.Flowable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;

/**
 * Created by Administrator on 2017/12/12.
 * thermometer device bluetooth status
 */

public class ThermometerActivity extends RxActivity implements View.OnClickListener, IBleStateListener, IPermissionsListener {

    private TextView tvContent;
    private TextView tvStart;
    private TextView tvStatus;
    private ProgressBar progress;
    private TextView tvContentDataArray;
    private SearchResult mDevice;
    private String mType = "";
    private String mSnNumber;
    private ZBleManager mBleManager;
    private String mMac;
    private boolean isEnableGetValue = true;
    private boolean isAutoConnect = false;
    private boolean isConnect = false;
    private boolean isScanning = false;
    private int ThermoModel=0;//0老体温计    1体温计E123

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_socket);
        findID();
        initScan();
        requestPermission();
        initListener();

    }

    private void requestPermission() {
        if (!ZPermissionUtil.getInstance().isPermissions(this, Manifest.permission.ACCESS_COARSE_LOCATION)) {
            ZPermissionUtil.getInstance().requestPermissions(this, this, Manifest.permission.ACCESS_COARSE_LOCATION);
        } else {
            initBleSetting();
        }
    }

    private void initScan() {
        mBleManager = ZBleManager.getInstance();
        mBleManager.initBle(this);
    }

    private void initListener() {
        tvStart.setOnClickListener(this);
    }


    boolean first = true;//只发一次信息包

    /**
     * 向蓝牙发送写入数据
     * Send write data to bluetooth
     *
     * @param data 写入的byte数据(The byte data that was written)
     */
    @SuppressLint("CheckResult")
    private void write(final String mac, final byte[] data) {
        if(ThermoModel==1)
        {
            mBleManager.write(mac, Contast.GATT_SERVICE_PRIMARYNEW1,
                    Contast.CHARACTERISTIC_WRITEABLENEW1, data, new IBleWriteListener() {
                        @Override
                        public void onWriteSuccess() {
                            Log.e("zdw", getString(R.string.write_data_ok) + Arrays.toString(data));
                        }

                        @Override
                        public void onWriteFailure(int code) {
                            Log.e("zdw", getString(R.string.write_data_error) + Arrays.toString(data));
//                        showMessage("未收到测量数据，请尝试重启设备并刷新页面");
                        }
                    });
        }
        else {
            mBleManager.write(mac, Contast.GATT_SERVICE_PRIMARY,
                    Contast.CHARACTERISTIC_WRITEABLE, data, new IBleWriteListener() {
                        @Override
                        public void onWriteSuccess() {
                            Log.e("zdw", getString(R.string.write_data_ok) + Arrays.toString(data));
                        }

                        @Override
                        public void onWriteFailure(int code) {
                            Log.e("zdw", getString(R.string.write_data_error) + Arrays.toString(data));
//                        showMessage("未收到测量数据，请尝试重启设备并刷新页面");
                        }
                    });
        }
    }

    /**
     * 订阅接受广播通知
     * Subscribe to receive broadcast notifications
     */
    private void indicate() {
        if(ThermoModel==1)
        {
            mBleManager.indicate(mDevice.getAddress(), Contast.GATT_SERVICE_PRIMARYNEW1,
                    Contast.CHARACTERISTIC_READABLENEW1, new IBleIndicateListener() {
                        @Override
                        public void onIndicateSuccess() {
                            Log.e("zdw", getString(R.string.indicate_success));
                            try {
                                Thread.sleep(500L);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            //发送00信息包
                            byte[] data_00 = ZHexUtil.hexStringToBytes(getSendHex(0));
                            //refreshLogView("\n写入数据(16进制)：" + Arrays.toString(ZHexUtil.setStr(ZHexUtil.bytes2HexString(data_00, data_00.length))));

                            write(mDevice.getAddress(), data_00);
                        }

                        @Override
                        public void onIndicateFailure(int code) {
                            Log.e("zdw", getString(R.string.indicate_failure) + "，code:" + "--" + code);
                            tvStatus.setText(R.string.bluetooth_search);
                            progress.setVisibility(View.VISIBLE);
                            bleScan();
                        }

                        @Override
                        public void onCharacteristicChanged(byte[] data) {
                            //refreshLogView("\n体温计返回(16进制)：" + Arrays.toString(ZHexUtil.setStr(ZHexUtil.bytes2HexString(data, data.length))));

                            Log.e("zdw", getString(R.string.get_device_data) + "--" + Arrays.toString(data));
                            getVersion(data);
                            getBleInfo(data);
                            showContent(data);
                        }
                    });

        }
        else
        {
            mBleManager.indicate(mDevice.getAddress(), Contast.GATT_SERVICE_PRIMARY,
                    Contast.CHARACTERISTIC_READABLE, new IBleIndicateListener() {
                        @Override
                        public void onIndicateSuccess() {
                            Log.e("zdw", getString(R.string.indicate_success));
                            try {
                                Thread.sleep(500L);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            //发送00信息包
                            byte[] data_00 = ZHexUtil.hexStringToBytes(getSendHex(0));
                            refreshLogView("\n写入数据(16进制)：" + Arrays.toString(ZHexUtil.setStr(ZHexUtil.bytes2HexString(data_00, data_00.length))));

                            write(mDevice.getAddress(), data_00);
                        }

                        @Override
                        public void onIndicateFailure(int code) {
                            Log.e("zdw", getString(R.string.indicate_failure) + "，code:" + "--" + code);
                            tvStatus.setText(R.string.bluetooth_search);
                            progress.setVisibility(View.VISIBLE);
                            bleScan();
                        }

                        @Override
                        public void onCharacteristicChanged(byte[] data) {
                            refreshLogView("\n体温计返回(16进制)：" + Arrays.toString(ZHexUtil.setStr(ZHexUtil.bytes2HexString(data, data.length))));

                            Log.e("zdw", getString(R.string.get_device_data) + "--" + Arrays.toString(data));
                            getVersion(data);
                            getBleInfo(data);
                            showContent(data);
                        }
                    });

        }


    }

    /**
     * 2.0以上协议的发包
     * Write data rule
     *
     * @param sendPack Write packet category
     * @return Write packet String data
     */
    public static String getSendHex(int sendPack) {
        String time = ZTimeTool.getCurrentDateTime("yy-MM-dd-HH-mm-ss");
        String[] arrTime = time.split("-");
        if (arrTime.length == 6) {
            int index0 = 90;
            int index1 = 10;
            int index2 = sendPack;//packet category
            int index3 = Integer.parseInt(arrTime[0]);//Year
            int index4 = Integer.parseInt(arrTime[1]);//Month
            int index5 = Integer.parseInt(arrTime[2]);//Day
            int index6 = Integer.parseInt(arrTime[3]);//Hour
            int index7 = Integer.parseInt(arrTime[4]);//Minute
            int index8 = Integer.parseInt(arrTime[5]);//Second
            int index9 = index0 + index1 + index2 + index3 + index4 + index5 + index6 + index7 + index8 + 2;
            if (index9 > 255) {
                index9 = index9 % 255;
            }
            byte[] data = new byte[]{(byte) index0, (byte) index1, (byte) index2, (byte) index3,
                    (byte) index4, (byte) index5, (byte) index6, (byte) index7, (byte) index8};

            String hexSend = ZHexUtil.encodeHexStr(data);
            String hexIndex9 = ZHexUtil.encodeHexStr(new byte[]{(byte) index9});
            int len = hexIndex9.length();
            String i9 = hexIndex9.substring(len - 2, len);
            return String.format("%s%s", hexSend, i9).toUpperCase();
        }
        return "";
    }


    private void findID() {
        tvContent = findViewById(R.id.tv_content);
        tvStart = findViewById(R.id.tv_start);
        tvStatus = findViewById(R.id.tv_status);
        progress = findViewById(R.id.progress);
        tvContentDataArray = findViewById(R.id.tv_content_data_array);
        tvContent.setMovementMethod(ScrollingMovementMethod.getInstance());
        tvContentDataArray.setMovementMethod(ScrollingMovementMethod.getInstance());
    }

    /**
     * 信息包
     * <p>
     * "00" package
     * Get the bluetooth device protocol version
     */
    private void getVersion(byte[] data) {
        if (null == data) return;
        int length = data.length;
        byte index0 = data[0];
        if (index0 != 85) return;
        byte index2 = data[2];
        if (index2 == 0) {
            first = false;
            //品牌
            mType = getTypeStr(data[4]);
        }
    }

    /**
     * 更新显示收发的数据
     *
     * @param msg
     */
    void refreshLogView(String msg) {
        tvContentDataArray.append(msg);
        int offset = tvContentDataArray.getLineCount() * tvContentDataArray.getLineHeight();
        if (offset > tvContentDataArray.getHeight()) {
            tvContentDataArray.scrollTo(0, offset - tvContentDataArray.getHeight());
        }
    }

    /**
     * 更新显示收到的结果
     *
     * @param msg
     */
    void refreshResultView(String msg) {
        tvContent.append(msg);
        int offset = tvContent.getLineCount() * tvContent.getLineHeight();
        if (offset > tvContent.getHeight()) {
            tvContent.scrollTo(0, offset - tvContent.getHeight());
        }
    }

    /**
     * @param data "3.0" protocol "00" package length:18
     * @param data "2.0" protocol "00" package length:15
     */
    private void getBleInfo(byte[] data) {
        if (null == data) return;
        if (data.length != 18 && data.length != 15) return;
        byte index0 = data[0];
        if (index0 != 85) return;
        byte index2 = data[2];
        if (index2 != 0) return;
        //sn
        byte[] snArray = new byte[9];
        System.arraycopy(data, 8, snArray, 0, 9);
        mSnNumber = ZDigitalTransTool.bytetoString(snArray);
        byte index4 = data[4];
        //品牌
        mType = getTypeStr(index4);

        String str = String.format("\n蓝牙名称：%s\nSN号:%s\n客户码:%s",
                mDevice.getName(), mSnNumber, mType);
        tvContent.append(str);
    }

    /**
     * get measure result
     * "2.0" above protocol "03" package length:12
     * "1.0" protocol "03" package length:14
     *
     * @param data received package data
     */
    private void showContent(byte[] data) {
        if (null == data) return;
        byte index0 = data[0];
        if (index0 != 85) return;
        byte index2 = data[2];
        if (index2 == 3) {//Device upload results
            byte index3 = data[3];//Year
            byte index4 = data[4];//Month
            byte index5 = data[5];//Day
            byte index6 = data[6];//Hour
            byte index7 = data[7];//Minute
            byte[] valueArr = {data[10], data[9]};
            //10+9 Convert to decimal,And then  divide by 100,get the temperature
            String strValue = ZHexUtil.encodeHexStr(valueArr);
            int value = Integer.valueOf(strValue, 16);
            Log.e("zdw", "value --" + value);
            //跟体温计结果显示保持一致：丢弃小数点后第二位
            String valueStr = StringUtil.formatTo1ROUNDDOWN((double) value / 100);
//            if (!TextUtils.isEmpty(mSnNumber)) {
//                String str = String.format("蓝牙名称：%s\nSN号:%s ; 客户码:%s\n日期:20%s-%s-%s %s:%s\n温度值:%s℃",
//                        mDevice.getName(),mSnNumber, mType
//                        , index3, index4, index5, index6, index7, valueStr);
            String str = String.format("\n日期:%s   温度值:%s℃", ZTimeTool.getCurrentDateTime("yyyy-MM-dd HH:mm:ss"), valueStr);
            refreshResultView(str);
//            } else {
//                String str = String.format("蓝牙名称：%s\n客户码:%s ; \n日期:20%s-%s-%s %s:%s,\n温度值:%s℃",mDevice.getName(), mType
//                        , index3, index4, index5, index6, index7, valueStr);
//                tvContent.setText(str);
//            }
        } else if (index2 == 5) {
            tvContent.append("\n" + getString(R.string.receive_finish));
        }
    }

    private String getTypeStr(byte type) {
        String typeStr = "";
        if (type == 0) {
            typeStr = getString(R.string.apple);
        } else if (type == 1) {
            typeStr = getString(R.string.bioland);
        } else if (type == 2) {
            typeStr = getString(R.string.haier);
        } else if (type == 3) {
            typeStr = getString(R.string.bioland);
        } else if (type == 4) {
            typeStr = getString(R.string.xiaomi);
        } else if (type == 5) {
            typeStr = getString(R.string.daotong);
        } else if (type == 6) {
            typeStr = "KANWEI";
        }
        return typeStr;
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.tv_start:
                tvStatus.setText(R.string.bluetooth_search);
                bleScan();
                break;
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        ZBleManager.getInstance().cancelScan();
    }

    @Override
    protected void onResume() {
        super.onResume();
        bleScan();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mDevice != null)
            ZBleManager.getInstance().destroy(mDevice.getAddress());
    }

    @SuppressLint("CheckResult")
    @Override
    public void onBleOpen() {
        Flowable.timer(500, TimeUnit.MILLISECONDS)
                .observeOn(AndroidSchedulers.mainThread())
                .compose(bindToLifecycle())
                .subscribe(new Consumer<Object>() {
                    @Override
                    public void accept(Object o) throws Exception {
                        bleScan();
                    }
                });
    }

    @SuppressLint("CheckResult")
    private void bleScan() {
        if (isScanning) return;
        Flowable.timer(500, TimeUnit.MILLISECONDS)
                .distinct()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .compose(bindToLifecycle())
                .subscribe(new Consumer<Object>() {
                    @Override
                    public void accept(Object o) throws Exception {
                        mBleManager.scan(new IBleScanListener() {
                            @Override
                            public void onScanStarted() {
                                Log.e("zdw", "---onScanStarted-------");
                                tvStatus.setText(R.string.search_the_bluetooth);
                                isScanning = true;
//                                progress.setVisibility(View.VISIBLE);
                            }

                            @Override
                            public void onScanCanceled() {
                                Log.e("zdw", "---onScanCanceled-------");
                                isScanning = false;
                            }

                            @Override
                            public void onScanStop() {
                                Log.e("zdw", "---onScanStop-------");
                                isScanning = false;
                                bleScan();
                            }

                            @Override
                            public void onDeviceFounded(SearchResult device) {
                                if (device == null) return;
                                if (!device.getName().contains("Bioland-IT")) return;
                                autoConnect(device);
                            }
                        });
                    }
                });

    }

    /**
     * 自动连接蓝牙
     * Automatic bluetooth connection
     */
    private void autoConnect(SearchResult device) {
        if (null == device) return;
        isAutoConnect = true;
        if (!isConnect) {
            isConnect = true;
            mMac = device.getAddress();
            mDevice = device;
            connect(device.getAddress());
        }
    }

    /**
     * 根据mac连接蓝牙
     * Connect to bluetooth according to MAC
     *
     * @param mac MAC address
     */
    private void connect(String mac) {
        mBleManager.connect(mac, new IBleConnectStatusListener() {
            @Override
            public void onStartConnect() {
                tvStart.setVisibility(View.GONE);
                isConnect = true;
                mBleManager.cancelScan();
                tvStatus.setText(R.string.start_connect);
                progress.setVisibility(View.VISIBLE);
            }

            @Override
            public void onConnectFail() {
                Log.e("zdw", "---onConnectFail");
                isConnect = false;
                tvStatus.setText(R.string.connect_failed);
                progress.setVisibility(View.GONE);
                tvStart.setVisibility(View.VISIBLE);
//                refreshList(true);
            }

            @Override
            public void onConnectSuccess(int code, BleGattProfile data, String mac) {
                Log.e("zdw", "---onConnectSuccess");
                progress.setVisibility(View.GONE);
                tvStatus.setText(R.string.connect_success);
                ThermoModel=0;
                for (BleGattService s :data.getServices()) {
                       if(s.getUUID().toString().equals(Contast.GATT_SERVICE_PRIMARYNEW1))
                       {
                           ThermoModel=1;
                           break;
                       }
                }


                indicate();

                isConnect = true;
                isEnableGetValue = true;
            }

            @Override
            public void onDisConnected(String mac) {
                Log.e("zdw", "---onDisConnected");
                tvStatus.setText(R.string.bluetooth_connect_cancel);
                isConnect = false;
                bleScan();
            }
        });
    }

    @Override
    public void onPermissionsSuccess() {
        initBleSetting();
    }

    @Override
    public void onPermissionsFail() {
        finish();
    }

    private void initBleSetting() {
        mBleManager = ZBleManager.getInstance();
        mBleManager.initBle(this);
        if (mBleManager.isSupportBle()) {
            if (!mBleManager.isBlueOpen()) {
                mBleManager.openBluetooth(this);
            } else {
                initConnectDevice();
            }
//            String[] names = {"Bioland-BGM", "Bioland", "bioland"};
        } else {
            Toast.makeText(this, R.string.not_support_bluetooth, Toast.LENGTH_SHORT).show();
        }
    }

    private void initConnectDevice() {
        bleScan();
    }
}
